package com.eternal.base.data.ble;

import androidx.annotation.Nullable;

import com.clj.fastble.data.BleDevice;
import com.eternal.base.concat.DeviceModel;
import com.eternal.base.global.BluetoothKey;
import com.eternal.base.protocol.BaseProtocol;
import com.eternal.base.utils.ByteUtils;
import com.eternal.framework.utils.KLog;

import java.util.concurrent.LinkedBlockingQueue;

import io.reactivex.Observable;
import io.reactivex.annotations.NonNull;
import io.reactivex.subjects.PublishSubject;

public class BleStatue {
    private final BleDevice device;
    private final LinkedBlockingQueue<Message> queue;
    private int sequence = 0;
    private final PublishSubject<DeviceModel> subject;
    private final int type;

    public BleStatue(BleDevice device) {
        this.device = device;
        type = BaseProtocol.parseScanRecordType(device);
        queue = new LinkedBlockingQueue<>();
        subject = PublishSubject.create();
    }

    boolean offer(Message message) {
        try {
            queue.put(message);
            return queue.peek() == message;
        } catch (InterruptedException e) {
            KLog.e("queue not offer");
            return false;
        }
    }

    boolean onError(Throwable throwable) {
        if (!queue.isEmpty()) {
            KLog.e(throwable);
            Message m = queue.poll();
            KLog.e(throwable.toString());
            KLog.e(ByteUtils.bytes2HexString(m.getPacket()));
            m.onErr(throwable);
            return !queue.isEmpty();
        }
        return false;
    }

    boolean onNext(byte[] packet) {
//        KLog.e(ByteUtils.bytes2HexString(packet));
        Message message = queue.peek();
        if (message == null) {
            KLog.e("null byte:" + ByteUtils.bytes2HexString(packet));
        } else {
            message.onNext(packet);
        }
        if (message instanceof SingleMessage) {
            queue.poll();
            return !queue.isEmpty();
        }
        return false;
    }

    boolean onComplement() {
        ((ObservableMessage) queue.poll()).onComplete();
        return !queue.isEmpty();
    }

    byte[] getPacket() {
        if (queue.peek() != null) {
            return queue.peek().getPacket();
        }
       return new byte[0];
    }

    int getLastSequence() {
        if (sequence == BluetoothKey.MAX_SEQUENCE) {
            sequence = 1;
        } else {
            ++sequence;
        }
        return sequence;
    }

    public void clear() {
        KLog.e("queue size:" + queue.size());
        queue.clear();
    }

    public BleDevice getDevice() {
        return device;
    }

    public String getMac() {
        return device.getMac();
    }

    public int getSize() {
        return queue.size();
    }

    public boolean remove(Message message) {
        queue.remove(message);
        KLog.e(" remove size: " + queue.size());
        return !queue.isEmpty();
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (obj != null) {
            if (obj == this) {
                return true;
            }
            if (obj instanceof BleDevice) {
                return ((BleDevice) obj).getMac().equals(device.getMac());
            }
        }
        return false;
    }

    void onNext(@NonNull DeviceModel device) {
        subject.onNext(device);
    }

    public int getType() {
        return type;
    }

    Observable<DeviceModel> getBroadcast() {
        return subject;
    }
}
